part of '../widgets.dart';

class VanCheckbox extends StatefulWidget {
  /// props - 选中值/标识符，通常为一个唯一的字符串或数字
  final dynamic value;

  /// props - 未选中值 - 使用[VanCheckboxGroup]无效
  final dynamic uncheckValue;

  /// props - 是否选中
  final bool? checked;

  /// props - 控制器
  /// <br> type: [VanCheckboxController] or [VanCheckedController]
  final Ref<bool>? controller;

  /// props - 形状，可选值为 square(默认: round)
  final VanCheckboxShape? shape;

  /// props - 是否禁用复选框(默认: false)
  final bool? disabled;

  /// props - 是否禁用复选框文本点击(默认: false)
  final bool labelDisabled;

  /// props - 文本位置，可选值为 left(默认: right)
  final VanCheckboxPosition? labelPosition;

  /// props - 图标大小，默认单位为 px(默认: 20px)
  final double? iconSize;

  /// props - 选中状态颜色(默认: #1989fa)
  final Color? checkedColor;

  /// props - 是否与复选框组绑定(默认: true)
  final bool bindGroup;

  /// props - 是否为不确定状态(默认: false)
  final bool? indeterminate;

  /// events - 当绑定值变化时触发的事件 回调参数(value) - 使用[VanCheckboxGroup]无效
  final Function(dynamic)? onChange;

  /// events - 点击单选框时触发
  final VoidCallback? onClick;

  final VanCheckboxStyle? style;

  /// props - [String]标签文本 <br>
  /// slots - [VanCheckboxBuilder] or [Widget]自定义文本 <br>
  final dynamic child;

  /// slots - [IconData] or [VanCheckboxBuilder] or [Widget]自定义图标 <br>
  final dynamic icon;

  const VanCheckbox({
    super.key,
    this.value = true,
    this.uncheckValue = false,
    this.checked,
    this.controller,
    this.shape,
    this.disabled,
    this.labelDisabled = false,
    this.labelPosition = VanCheckboxPosition.right,
    this.iconSize,
    this.checkedColor,
    this.bindGroup = true,
    this.indeterminate = false,
    this.onChange,
    this.onClick,
    this.style,
    this.child,
    this.icon,
  });

  @override
  State<VanCheckbox> createState() => _VanCheckboxState();
}

class _VanCheckboxState extends State<VanCheckbox> {
  Ref<bool>? controller;
  VanCheckboxGroup? group;

  @override
  void initState() {
    super.initState();
    controller = widget.controller ?? ref(widget.checked ?? false);
  }

  @override
  void dispose() {
    if (group?.controller is VanCheckboxGroupController) {
      (group?.controller as VanCheckboxGroupController)._states.remove(this);
    }
    controller?.dispose();
    super.dispose();
  }

  VanCheckboxStyle getComputedStyle(BuildContext context, {bool checked = false, bool disabled = false}) {
    final style = widget.style;
    if (style?.isNonNull == true) return style!;
    double? iconSize = style?.iconSize;
    Color? iconColor = style?.iconColor;
    double? duration = style?.duration;
    double? labelMargin = style?.labelMargin;
    Color? labelColor = style?.labelColor;

    group ??= VanProvider.of<VanCheckboxGroup>(context);

    if (disabled) {
      iconColor ??= kVanCheckboxDisabledIconColor.toColor(context);
      labelColor ??= kVanCheckboxDisabledLabelColor.toColor(context);
    } else if (checked) {
      iconColor ??= widget.checkedColor ?? group?.checkedColor;
      iconColor ??= kVanCheckboxCheckedIconColor.toColor(context);
    }

    iconSize ??= kVanCheckboxIconSize.toDouble(context);
    iconColor ??= kVanCheckboxIconColor.toColor(context);
    duration ??= kVanCheckboxDuration.toDouble(context);
    labelMargin ??= kVanCheckboxLabelMargin.toDouble(context);
    labelColor ??= kVanCheckboxLabelColor.toColor(context);

    return VanCheckboxStyle(
      iconSize: iconSize,
      iconColor: iconColor,
      duration: duration,
      labelMargin: labelMargin,
      labelColor: labelColor,
    );
  }

  @override
  Widget build(BuildContext context) {
    group = VanProvider.of<VanCheckboxGroup>(context);
    if (group?.controller is VanCheckboxGroupController) {
      (group!.controller as VanCheckboxGroupController)._states.add(this);
    }
    VanCheckboxShape? shape = widget.shape;
    bool? checked = widget.checked;
    bool? initDisabled = widget.disabled;
    shape ??= group?.shape;
    initDisabled ??= group?.disabled;

    shape ??= VanCheckboxShape.square;
    checked ??= false;
    initDisabled ??= false;

    GestureTapCallback? onTap;

    ValueNotifier? listen = widget.controller;
    if (widget.bindGroup) listen ??= group?.controller;
    listen ??= VanCheckboxController(widget.checked ?? false, indeterminate: widget.indeterminate ?? false);
    if (listen is VanCheckboxController) controller = listen;

    final gc = group?.controller;
    return ValueListenableBuilder(
      valueListenable: listen,
      builder: (ctx, value, child) {
        bool checked = false;
        if (value is bool) {
          checked = value;
        } else if (value is List) {
          checked = value.contains(widget.value);
        }

        bool disabled = initDisabled ?? false;
        if (gc is VanCheckboxGroupController && gc.max > 0) {
          if (initDisabled == false && !checked) {
            disabled = gc.value.length >= gc.max;
          }
        }

        final style = getComputedStyle(context, checked: checked, disabled: disabled);
        if (disabled == false) {
          onTap = () {
            if (widget.bindGroup && group?.controller != null) {
              final ctrl = group!.controller;
              if (ctrl is VanCheckboxGroupController) {
                ctrl.toggleValue = widget.value;
              } else {
                _logger.w("未实现不是VanCheckboxGroupController");
              }
            } else if (controller != null) {
              controller!.value = !checked;
              if (widget.onChange != null) {
                widget.onChange!(controller!.value ? widget.value : widget.uncheckValue);
              }
            }
            if (widget.onClick != null) widget.onClick!();
          };
        }

        bool indeterminate;
        if (controller is VanCheckedController) {
          indeterminate = (controller as VanCheckboxController).indeterminate;
        } else {
          indeterminate = widget.indeterminate ?? false;
        }

        Widget icon;
        if (widget.icon is Widget) {
          icon = widget.icon;
        } else if (widget.icon is VanCheckboxBuilder) {
          icon = widget.icon!(VanCheckboxScope(checked: checked, disabled: disabled, indeterminate: indeterminate));
        } else if (widget.icon is IconData) {
          icon = Icon(widget.icon);
        } else {
          if (widget.icon != null) {
            _logger.e(ArgumentError("VanCheckbox.icon only type support [IconData] or [Widget] or [VanCheckboxBuilder]", "icon"));
          }
          IconData iconData;
          if (shape == VanCheckboxShape.square) {
            iconData = iconData = checked
                ? Icons.check_box_rounded
                : indeterminate
                    ? Icons.check_box_outlined
                    : Icons.square_outlined;
          } else {
            iconData = iconData = checked
                ? Icons.check_circle_rounded
                : indeterminate
                    ? Icons.check_circle_outline
                    : Icons.radio_button_unchecked_rounded;
          }
          icon = Icon(iconData);
        }

        if (icon is! Icon) icon = SizedBox(width: style.iconSize, height: style.iconSize, child: icon);

        final iconThemeData = Theme.of(context).iconTheme.copyWith(size: style.iconSize, color: style.iconColor);
        icon = IconTheme(data: iconThemeData, child: icon);

        if (disabled == false && widget.labelDisabled) {
          icon = GestureDetector(onTap: onTap, child: icon);
        }

        Widget? label;
        if (widget.child is String) {
          if (widget.child.isNotEmpty) label = Text(widget.child!);
        } else if (widget.child is Widget) {
          label = widget.child;
        } else if (widget.child is VanCheckboxBuilder) {
          label = widget.child!(VanCheckboxScope(checked: checked, disabled: disabled, indeterminate: indeterminate));
        } else {
          if (widget.child != null) {
            _logger.e("VanCheckbox.child only type support [String] or [Widget] or [VanCheckboxBuilder]");
          }
        }

        Widget w;
        if (label != null) {
          label = DefaultTextStyle(
            style: TextStyle(color: style.labelColor),
            child: label,
          );
          List<Widget> ws = [icon, SizedBox(width: style.labelMargin), label];
          if (widget.labelPosition != VanCheckboxPosition.right) ws = ws.reversed.toList();
          w = Row(children: ws);
        } else {
          w = Align(alignment: Alignment.centerLeft, child: icon);
        }

        if (disabled == false && !widget.labelDisabled) {
          w = GestureDetector(onTap: onTap, child: w);
        }

        if (group != null && group!.children?.lastOrNull != widget) {
          if (group!.direction == VanCheckboxDirection.horizontal) {
            w = Padding(
              padding: EdgeInsets.only(right: style.labelMargin ?? 0),
              child: w,
            );
          } else {
            w = Padding(
              padding: EdgeInsets.only(bottom: (style.labelMargin ?? 0) / 2),
              child: w,
            );
          }
        }

        return w;
      },
    );
  }
}

class VanCheckboxScope {
  final bool checked;
  final bool indeterminate;
  final bool disabled;

  VanCheckboxScope({required this.checked, required this.disabled, required this.indeterminate});
}

typedef VanCheckboxBuilder = Widget Function(VanCheckboxScope scope);

class VanCheckboxController extends VanCheckedController {
  bool _indeterminate;

  bool get indeterminate => _indeterminate;

  set indeterminate(bool newValue) {
    if (newValue == _indeterminate) return;
    _indeterminate = newValue;
    notifyListeners();
  }

  VanCheckboxController(super.checked, {bool indeterminate = false}) : _indeterminate = false;
}
